import { MongoClient, Db, ServerApiVersion, SortDirection } from "mongodb"
import Movies from './movies/index.ts'
import Haiku from './haiku/index.ts'
import { Rating } from './movies/types.ts'

const uri = "mongodb+srv://test:dev1024.@aaron.k7jia.mongodb.net/?retryWrites=true&w=majority&appName=Aaron"


const client = new MongoClient(uri)

client.connect().then(async () => {
  console.log('数据库连接成功')
  const database = client.db('sample_mflix')

  // const cursor = database.collection('movies').find({}).limit(2)
  // console.log(cursor)
  // movie(database)
  // haiku(database)


  // 获取数据库中的集合信息
  // database.command({ dbStats: 1 }).then(info => console.dir(info))

  // vernier(database)

  // distinctValue(database)
  skipFunction(database)
})

async function movie(database: Db) {
  const movies = new Movies(database)

  // movies.findOne({ title: "The Room" },
  //   {
  //     sort: { rating: -1 },
  //     projection: { _id: 0, title: 1, imdb: 1 },
  //   })

  // const res = await movies.find(
  //   {
  //     runtime: {
  //       $lt: 15
  //     }
  //   },
  //   {
  //     sort: { title: 1 },
  //     projection: { _id: 0, title: 1, imdb: 1 },
  //   }
  // )
  // for await (const doc of res) {
  //   console.dir(doc)
  // }

  // movies.updateOne({ title: 'Random Harvest' }, {
  //   $set: {
  //     plot: `A Harvest`
  //   }
  // }, { upsert: true })

  // movies.updateMany({ rated: Rating.G },
  //   {
  //     $set: {
  //       random_review: `After viewing I am ${100 * Math.random()
  //         }% more satisfied with life.`,
  //     },
  //   })

  // movies.replaceOne({ title: { $regex: "The Cat from" } }, { title: `The Cat from Sector ${Math.floor(Math.random() * 1000 + 1)}` })

  // movies.deleteOne({ title: 'Annie Hall' })

  // movies.deleteMany({ title: { $regex: 'Santa' } })

  // movies.countDocuments({ title: { $regex: 'Annie' } })

  // movies.estimatedDocumentCount()

  movies.distinct('year', { directors: 'Barbra Streisand' })
}

async function haiku(database: Db) {
  const haiku = new Haiku(database)

  haiku.insertOne({
    title: 'Record of a shriveled Datum',
    content: "No bytes, no problem. Just insert a document, in MongoDB",
  })

  // haiku.insertMany([
  //   { name: 'cake', healthy: false },
  //   {name: 'lettuce', healthy: true},
  //   {name: 'donut', healthy: false},
  // ])
}

// 游标：在 mongodb 中意指查询结果的合集。由于查询的结果可能是数量巨大的文档集，因此会返回一个称为 游标 的对象，这个对象可以查询所标识的文档。游标会分批获取文档，减少内存消耗和网络带宽。
async function vernier(database: Db) {
  // 获取电影表
  const movies = database.collection('movies')
  // 获取数据库中的集合数据，游标

  // 1. 异步迭代
  // const cursor1 = movies.find({}).limit(2)
  // for await (const doc of cursor1) {
  //   console.log(doc)
  // }

  // 2. 手动迭代
  const cursor2 = movies.find({}).limit(2)
  while (await cursor2.hasNext()) {
    console.log(cursor2.next())
  }

  // 3. 想直接获取所有的数据, 使用 `toArray` 来获取所有数据。toArray 会将所有数据加载到内存中。
  // const cursor3 = await movies.find({}).limit(2).toArray()
  // console.log(cursor3)

  // 4. 数据流，通过管道传递 JavaScript 对象，而不是传递缓冲区或字符串
  // movies.find({}).limit(2).stream().on('data', (doc) => {
  // console.log(doc)
  // })

  // 5. 事件 API
  // const cursor = movies.find({})
  // the "data" event is fired once per document
  // cursor.on("data", data => console.log(data))

  // 6. 重置游标位置
  await cursor2.rewind()
  cursor2.toArray().then(res => console.log(res))

  // 关闭游标
  // if (!cursor2.closed) {
  //   try {
  //     cursor2.close()
  //   } catch (error) {
  //     console.log('报错了')
  //   }
  // } else {
  //   console.log('会话已关闭')
  // }
}


async function distinctValue(database: Db) {
  const movies = database.collection('movies')
  movies.distinct('year', { directors: 'Barbra Streisand' })
}

async function skipFunction(database: Db) {
  const myColl = database.collection("fruits")

  await myColl.insertMany([
    { "name": "apples", "qty": 5, "rating": 3 },
    { "name": "bananas", "qty": 7, "rating": 1 },
    { "name": "oranges", "qty": 6, "rating": 2 },
    { "name": "avocados", "qty": 3, "rating": 5 },
  ])

  const query = {}
  const options = { sort: { rating: -1 as const }, skip: 2 }
  const cursor = myColl.find(query, options)
  for await (const doc of cursor) {
    console.dir(doc)
  }

  // 等效写法
  // myColl.find(query, { sort: { rating: -1}, skip: 2});
  // myColl.find(query).sort({rating: -1}).skip(2);
}